package com.hontech.kaltaapp.ui.parts

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.FrameLayout
import androidx.recyclerview.widget.RecyclerView
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.hontech.kaltaapp.R
import com.hontech.kaltaapp.device.nozzleCtrl
import com.hontech.kaltaapp.store.COOKING_TYPE_MOVE_STEAM
import com.hontech.kaltaapp.store.COOKING_TYPE_STEAM
import com.hontech.kaltaapp.store.COOKING_TYPE_WAIT
import com.hontech.kaltaapp.store.COOKING_TYPE_WATER
import com.hontech.kaltaapp.store.CookingAction
import com.hontech.kaltaapp.store.CookingExecutable
import com.hontech.kaltaapp.store.MoveSteamInfo
import com.hontech.kaltaapp.store.SteamInfo
import com.hontech.kaltaapp.store.WaitInfo
import com.hontech.kaltaapp.store.WaterInfo
import com.hontech.kaltaapp.ui.dialog.runProg
import com.hontech.kaltaapp.ui.dialog.showSucc
import com.hontech.kaltaapp.ui.view.LabelInput
import com.hontech.kaltaapp.ui.view.LabelSpinner
import com.hontech.kaltaapp.ui.view.LabelSwitch
import com.hontech.kaltaapp.ui.view.LabelTextInput
import com.hontech.kaltaapp.utils.onClick
import com.hontech.kaltaapp.utils.stringsById

class CookingConfigParts(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs) {

    private val rv: RecyclerView
    private val sp: LabelSpinner
    private val btnRefresh: Button
    private val ltiName: LabelTextInput
    private val btnExec: Button
    private val btnNewWait: Button
    private val btnNewWater: Button
    private val btnNewSteam: Button
    private val btnNewSteam2: Button
    private val btnSave: Button

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.parts_cooking_config, this)
        rv = view.findViewById(R.id.id_cc_rv)
        sp = view.findViewById(R.id.id_cc_ls_action_sel)
        ltiName = view.findViewById(R.id.id_cc_lti_name)
        btnRefresh = view.findViewById(R.id.id_cc_btn_refresh)
        btnExec = view.findViewById(R.id.id_cc_btn_exec)
        btnNewWait = view.findViewById(R.id.id_cc_btn_new_wait)
        btnNewWater = view.findViewById(R.id.id_cc_btn_new_water)
        btnNewSteam = view.findViewById(R.id.id_cc_btn_new_steam)
        btnNewSteam2 = view.findViewById(R.id.id_cc_btn_new_move_steam)
        btnSave = view.findViewById(R.id.id_cc_btn_save_all)

        val adapter = ConfigAdapter()
        rv.adapter = adapter
        rv.layoutManager = FlexboxLayoutManager(context, FlexDirection.ROW, FlexWrap.WRAP)

        btnNewWait.setOnClickListener {
            val waitInfo = WaitInfo("", WaitInfo.WAIT_WATER, 50)
            adapter.newWait(waitInfo)
        }

        btnNewWater.setOnClickListener {
            val waterInfo = WaterInfo("", 0, 50, 0)
            adapter.newWater(waterInfo)
        }

        btnNewSteam.setOnClickListener {
            val steamInfo = SteamInfo("", 0, 10)
            adapter.newSteam(steamInfo)
        }

        btnNewSteam2.setOnClickListener {
            val moveSteamInfo = MoveSteamInfo("", 0, 10, 10)
            adapter.newMoveSteam(moveSteamInfo)
        }

        btnSave.onClick {
            runProg("保存", "保存") {
                adapter.save(ltiName.text())
            }
        }

        btnRefresh.onClick {
            runProg("刷新", "刷新") {
                val result = CookingAction.get()
                sp.setItems(result.map { it.name })
                sp.setSelectFunc { _, index ->
                    adapter.refresh(result[index])
                }
            }
        }

        btnExec.onClick {
            adapter.exec()
        }
    }

}


private abstract class BaseItem(view: View) : RecyclerView.ViewHolder(view) {
    abstract fun setUp(info: CookingExecutable)

    abstract val btnDel: Button
}

private class WaitItem(view: View) : BaseItem(view) {

    private val sp = view.findViewById<LabelSpinner>(R.id.id_wait_ls_type)
    private val liName = view.findViewById<LabelTextInput>(R.id.id_wait_lti_name)
    private val liValue = view.findViewById<LabelInput>(R.id.id_wait_lti_value)
    private val btnSave = view.findViewById<Button>(R.id.id_wait_btn_save)

    override val btnDel: Button = view.findViewById(R.id.id_wait_btn_del)

    override fun setUp(info: CookingExecutable) {
        val waitInfo = info as WaitInfo
        sp.setSelectIndex(waitInfo.waitType)
        liName.setText(info.name)
        liValue.set(info.value)
        btnSave.setOnClickListener {
            waitInfo.waitType = sp.selectIndex()
            waitInfo.name = liName.text()
            waitInfo.value = liValue.textInt()
            showSucc("保存")
        }
    }
}

private class WaterItem(view: View) : BaseItem(view) {

    private val liName = view.findViewById<LabelTextInput>(R.id.id_water_lti_name)
    private val limm = view.findViewById<LabelInput>(R.id.id_water_li_mm)
    private val liml = view.findViewById<LabelInput>(R.id.id_water_li_ml)
    private val spHeat = view.findViewById<LabelSwitch>(R.id.id_water_ls_open_heat)
    private val btnSave = view.findViewById<Button>(R.id.id_water_btn_save)
    override val btnDel: Button = view.findViewById(R.id.id_water_btn_del)

    override fun setUp(info: CookingExecutable) {
        val waterInfo = info as WaterInfo
        liName.setText(waterInfo.name)
        limm.set(waterInfo.mm)
        liml.set(waterInfo.ml)
        spHeat.set( waterInfo.openHeat != 0 )
        btnSave.setOnClickListener {
            waterInfo.name = liName.text()
            waterInfo.mm = limm.textInt()
            waterInfo.ml = liml.textInt()
            waterInfo.openHeat = if (spHeat.isChecked()) 1 else 0
            showSucc("保存")
        }
    }
}

private class SteamItem(view: View) : BaseItem(view) {

    private val liName = view.findViewById<LabelTextInput>(R.id.id_steam_lti_name)
    private val limm = view.findViewById<LabelInput>(R.id.id_steam_li_mm)
    private val litime = view.findViewById<LabelInput>(R.id.id_steam_li_time)
    private val btnSave = view.findViewById<Button>(R.id.id_steam_btn_save)
    override val btnDel: Button = view.findViewById(R.id.id_steam_btn_del)

    override fun setUp(info: CookingExecutable) {
        val steamInfo = info as SteamInfo
        liName.setText(steamInfo.name)
        limm.set(steamInfo.mm)
        litime.set(steamInfo.duration)
        btnSave.setOnClickListener {
            steamInfo.name = liName.text()
            steamInfo.mm = limm.textInt()
            steamInfo.duration = litime.textInt()
            showSucc("保存")
        }
    }
}

private class MoveSteamItem(view: View) : BaseItem(view) {

    private val liName = view.findViewById<LabelTextInput>(R.id.id_move_steam_lti_name)
    private val limm = view.findViewById<LabelInput>(R.id.id_move_steam_li_mm)
    private val limm2 = view.findViewById<LabelInput>(R.id.id_move_steam_li_mm2)
    private val litime = view.findViewById<LabelInput>(R.id.id_move_steam_li_time)
    private val btnSave = view.findViewById<Button>(R.id.id_move_steam_btn_save)
    override val btnDel: Button = view.findViewById(R.id.id_move_steam_btn_del)
    override fun setUp(info: CookingExecutable) {
        val moveSteamInfo = info as MoveSteamInfo
        liName.setText(moveSteamInfo.name)
        limm.set(moveSteamInfo.mm)
        limm2.set(moveSteamInfo.mm2)
        litime.set(moveSteamInfo.duration)
        btnSave.setOnClickListener {
            moveSteamInfo.name = liName.text()
            moveSteamInfo.mm = limm.textInt()
            moveSteamInfo.mm2 = limm2.textInt()
            moveSteamInfo.duration = litime.textInt()
            showSucc("保存")
        }
    }
}

private class ConfigAdapter : RecyclerView.Adapter<BaseItem>() {

    private var action = CookingAction("")

    fun refresh(action: CookingAction) {
        this.action = action
        notifyDataSetChanged()
    }
    suspend fun save(name: String) {
        action.name = name
        action.save()
    }

    
    suspend fun exec() {
        runProg(action.name, "执行") {
            for (action in action.actions) {
                it.setMsg("执行:${action.name}")
                action.exec()
            }
            it.setMsg("喷嘴复位")
            nozzleCtrl(0)
        }
    }

    fun newWait(waitInfo: WaitInfo) {
        val len = action.actions.size
        action.actions.add(waitInfo)
        notifyItemInserted(len)
    }

    fun newWater(waterInfo: WaterInfo) {
        val len = action.actions.size
        action.actions.add(waterInfo)
        notifyItemInserted(len)
    }

    fun newSteam(steamInfo: SteamInfo) {
        val len = action.actions.size
        action.actions.add(steamInfo)
        notifyItemInserted(len)
    }

    fun newMoveSteam(moveSteamInfo: MoveSteamInfo) {
        val len = action.actions.size
        action.actions.add(moveSteamInfo)
        notifyItemInserted(len)
    }

    override fun getItemCount(): Int {
        return action.actions.size
    }

    override fun onBindViewHolder(holder: BaseItem, position: Int) {
        val info = action.actions[position]
        holder.setUp(info)
        holder.btnDel.setOnClickListener {
            action.actions.removeAt(position)
            notifyDataSetChanged()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseItem {
        val item = when (viewType) {
            COOKING_TYPE_WAIT -> WaitItem(LayoutInflater.from(parent.context).inflate(R.layout.item_cooking_wait, parent, false))
            COOKING_TYPE_WATER -> WaterItem(LayoutInflater.from(parent.context).inflate(R.layout.item_cooking_water, parent, false))
            COOKING_TYPE_STEAM -> SteamItem(LayoutInflater.from(parent.context).inflate(R.layout.item_cooking_steam, parent, false))
            COOKING_TYPE_MOVE_STEAM -> MoveSteamItem(LayoutInflater.from(parent.context).inflate(R.layout.item_cooking_move_steam, parent, false))
            else -> throw IllegalStateException("未知类型")
        }
        return item
    }

    override fun getItemViewType(position: Int): Int {
        return action.actions[position].type
    }
}










